package com.foreveross.crawl.adapter.sub.impl20140402.v3;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import net.sf.json.JSONObject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.util.EntityUtils;

import com.foreveross.crawl.adapter.AbstractAdapter;
import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.common.util.ClassUtils;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.common.util.browser.BrowserVersionSub;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.CabinRelationEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.proxyip.ProxyIpModel;
import com.foreveross.taskservice.common.bean.TaskModel;
/**
 * 天津航空
 * @author Administrator
 *
 */
public class TianjinAdapter extends AbstractAdapter {
	HttpClient client = null;

	public TianjinAdapter(TaskModel taskQueue) {
		super(taskQueue);
	}

	
	public String getUrl1(String cabinType) {
		String area = taskQueue.getIsInternational() == 1 ? "" : "area=LOCAL";
		String returnDate = StringUtils.isBlank(taskQueue.getReturnGrabDate()) ? "" : ("returnDate=" + taskQueue.getReturnGrabDate());
		cabinType = "cabinType=" + cabinType;// economyClass FClass
		String tripType = taskQueue.getIsReturn() == 1 ? "tripType=ROUNDTRIP" : "ONEWAY";
		String url = "http://www.tianjin-air.com/flight/searchflight.action?" + area + "&" + cabinType + "&dstCity=" + taskQueue.getToCity() + "&flightDate=" + taskQueue.getFlightDate() + "&orgCity=" + taskQueue.getFromCity() + "&" + returnDate
				+ "&" + tripType;
		// System.out.println(url);
		return url;
	}

	public String getUrl2(String cabinType, String orgCity, String dstCity) {
		String returnDate = StringUtils.isBlank(taskQueue.getReturnGrabDate()) ? "" : ("returnDate=" + taskQueue.getReturnGrabDate());
		cabinType = "cabinType=" + cabinType;// economyClass FClass
		String tripType = taskQueue.getIsReturn() == 1 ? "tripType=ROUNDTRIP" : "ONEWAY";
		String url = "http://www.tianjin-air.com/flight/flightresult.action?" + cabinType + "&dstCity=" + dstCity + "&flightDate=" + taskQueue.getFlightDate() + "&orgCity=" + orgCity + "&" + tripType + "&" + returnDate;
		// System.out.println(url);
		return url;
	}

	@Override
	public Object fetch(String url) throws Exception {
//		List<AbstractPlaneInfoEntity> result = new ArrayList<AbstractPlaneInfoEntity>();
//		List<AbstractPlaneInfoEntity> fClasses = this.fetchFromCabinType("FClass");
		List<AbstractPlaneInfoEntity> result = this.fetchFromCabinType("economyClass");
//		Map<String, AbstractPlaneInfoEntity> fClassMap = ClassUtils.getKeyMapByList(fClasses, "flightNo");
//		Map<String, AbstractPlaneInfoEntity> economyClassMap = ClassUtils.getKeyMapByList(economyClasses, "flightNo");
//		Set<String> aSet = fClassMap.keySet(), bSet = economyClassMap.keySet();
//		List<AbstractPlaneInfoEntity> cList = new ArrayList<AbstractPlaneInfoEntity>();// 没有交集的集合
//		List<AbstractPlaneInfoEntity> dList = new ArrayList<AbstractPlaneInfoEntity>();// 并集
//		for (String a : aSet) {
//			if (!bSet.contains(a)) {
//				cList.add(fClassMap.get(a));
//			} else {
//				AbstractPlaneInfoEntity fClass = fClassMap.get(a);
//				AbstractPlaneInfoEntity economy = economyClassMap.get(a);
//				if (taskQueue.getIsReturn() == 1) {
//					Set<CabinEntity> cabins = PlaneInfoEntityBuilder.getDoubleEntity(fClass).getCabins();
//					Set<CabinRelationEntity> relations = PlaneInfoEntityBuilder.getDoubleEntity(fClass).getCabinRelations();
//					PlaneInfoEntityBuilder.getDoubleEntity(economy).getCabins().addAll(cabins);
//					PlaneInfoEntityBuilder.getDoubleEntity(economy).getCabinRelations().addAll(relations);
//				} else {
//					Set<CabinEntity> cabins = PlaneInfoEntityBuilder.getSingleEntity(fClass).getCabins();
//					PlaneInfoEntityBuilder.getSingleEntity(economy).getCabins().addAll(cabins);
//				}
//				dList.add(economy);
//			}
//		}
//		for (String b : bSet) {
//			if (!aSet.contains(b)) {
//				cList.add(economyClassMap.get(b));
//			}
//		}
//		result.addAll(cList);
//		result.addAll(dList);
		PlaneInfoEntityBuilder.buildLimitPrice(result);
		return result;
	}

	public List<AbstractPlaneInfoEntity> fetchFromCabinType(String cabinType) throws Exception {
		//2014-09-26 发现此段代码暂时没有用处
//		HttpPost request = null;
//		request = new HttpPost(getUrl1(cabinType));
//		loadRequestHeader(request);
//		super.excuteRequest(super.getHttpClient(), request, false);
		List<AbstractPlaneInfoEntity> toFlights = null;
		List<AbstractPlaneInfoEntity> backFlights = null;
		if (taskQueue.getIsReturn() == 1) {
			toFlights = this.getFlight(cabinType, taskQueue.getFromCity(), taskQueue.getToCity(), 2);
			backFlights = this.getFlight(cabinType, taskQueue.getToCity(), taskQueue.getFromCity(), 3);
			if (toFlights == null || toFlights.size() == 0 || backFlights == null || backFlights.size() == 0) {
				return new ArrayList<AbstractPlaneInfoEntity>();
			}
			Set<ReturnDoublePlaneInfoEntity> backSet = new HashSet<ReturnDoublePlaneInfoEntity>();
			for (AbstractPlaneInfoEntity backFlight : backFlights) {
				ReturnDoublePlaneInfoEntity back = (ReturnDoublePlaneInfoEntity) backFlight;
				backSet.add(back);
			}
			for (AbstractPlaneInfoEntity to : toFlights) {
				DoublePlaneInfoEntity flight = (DoublePlaneInfoEntity) to;
				Set<ReturnDoublePlaneInfoEntity> returnFlght = flight.getReturnPlaneInfos();
				returnFlght.addAll(backSet);
			}
			PlaneInfoEntityBuilder.buildRelation(toFlights, backFlights);
		} else {
			toFlights = this.getFlight(cabinType, taskQueue.getFromCity(), taskQueue.getToCity(), 1);
		}
		return toFlights;
	}
	private String fetchData(String cabinType, String fromCity, String toCity) throws Exception{
		HttpPost request = null;
		String data = null;
		try{
			request = new HttpPost(getUrl2(cabinType, fromCity, toCity));
			request.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
			request.setHeader("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3");
			request.setHeader("Host", "www.tianjin-air.com");
			request.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			request.setHeader("Referer", "http://www.tianjin-air.com/flight/searchflight.action");
			request.setHeader("User-Agent", BrowserVersionSub.FIREFOX_31.getUserAgent());
			request.setHeader("Vary", "	Accept-Encoding,User-Agent");
			data = super.excuteRequest(super.getHttpClient(), request, true);  //获取JSON数据 ，通过JS解析出Html。
			super.appendPageContents(data);
			return data;
		}finally{
			request = null;
			data = null;
		}
	}
	public <T> List<AbstractPlaneInfoEntity> getFlight(String cabinType, String fromCity, String toCity, Integer type) throws Exception {
		List<AbstractPlaneInfoEntity> result = new ArrayList<AbstractPlaneInfoEntity>();
		String jsonHtml = null;
		ScriptEngineManager sem = null;
		ScriptEngine engine = null;
		InputStream is = null;
		try{
			jsonHtml = this.fetchData(cabinType, fromCity, toCity);
			JSONObject j = JSONObject.fromObject(jsonHtml);
			if(j.getJSONArray("flights").size() == 0){//木有航班
				throw new FlightInfoNotFoundException();
			}
			 sem = new ScriptEngineManager();
			 engine = sem.getEngineByName("javascript");
			 is = TianjinAdapter.class.getClassLoader().getResourceAsStream("js/tianjin.js");
			engine.eval(IOUtils.toString(is));
			if (engine instanceof Invocable) {
				Invocable invoke = (Invocable) engine;
				String html = (String) invoke.invokeFunction("renderFlight", jsonHtml, "selectedFlight");
				List<String> flightList = RegHtmlUtil.retrieveLinks(html, getRegex3(), 1);
				List<List<String>> flights = RegHtmlUtil.retrieveLinkss(flightList.get(0), getRegex4());
				for (List<String> cells : flights) {
					String flightNo = cells.get(2);
					String startTime = cells.get(3);
					String endTime = cells.get(4);
					AbstractPlaneInfoEntity plane = null;
					// plane.setFlightNo(flightNo);
					Set<CabinEntity> cabinEntitys = null;
					Set<ReturnCabinEntity> returnCabinEntitys = null;
					if (type == 3) {
						plane = PlaneInfoEntityBuilder.getReturnTrip(taskQueue, "GS", "津航", "天津航空", startTime, endTime, flightNo, null, "", null, "");
						ReturnDoublePlaneInfoEntity returnPlaneInfo = PlaneInfoEntityBuilder.getReturnDoubleEntity(plane);
						returnCabinEntitys = returnPlaneInfo.getReturnCabins();
					} else {
						plane = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "GS", "津航", "天津航空", startTime, endTime, flightNo, null, "", null, "");
						if (type == 1) {
							SinglePlaneInfoEntity single = PlaneInfoEntityBuilder.getSingleEntity(plane);
							cabinEntitys = single.getCabins();
						} else {
							DoublePlaneInfoEntity doublePlane = PlaneInfoEntityBuilder.getDoubleEntity(plane);
							cabinEntitys = doublePlane.getCabins();
						}
					}
					result.add(plane);
					List<List<String>> cabins = RegHtmlUtil.retrieveLinkss(cells.get(5), this.getRegex5());
					for (List<String> cabin : cabins) {
						String cabinName = cabin.get(1);
						String productName = cabin.get(2);
						Double price = PlaneInfoEntityBuilder.getDouble(cabin.get(3));
						if (type == 3) {
							ReturnCabinEntity cabinEntity = new ReturnCabinEntity();
							cabinEntity.setCabinType(getCabinTypeName(cabinType));
							cabinEntity.setProductName(productName);
							cabinEntity.setSubCabinName(cabinName);
							cabinEntity.setPrice(price);
							// tempCabins.add(cabinEntity);
							returnCabinEntitys.add(cabinEntity);
						} else {
							CabinEntity cabinEntity = new CabinEntity();
							cabinEntity.setCabinType(getCabinTypeName(cabinType));
							cabinEntity.setProductName(productName);
							cabinEntity.setSubCabinName(cabinName);
							cabinEntity.setPrice(price);
							cabinEntitys.add(cabinEntity);
							// tempCabins.add(cabinEntity);
						}
	
					}
				}
			}
		}finally{
			IOUtils.closeQuietly(is);
			is = null;
			 jsonHtml = null;
			 sem = null;
			 engine = null;
		}
		return result;
	}

	public String getCabinTypeName(String type) {
		if ("FClass".equals(type)) {
			return "公务舱/头等舱";
		} else {
			return "经济舱";
		}
	}

	public AbstractPlaneInfoEntity getPlaneEntity(Integer type) {
		switch (type) {
		case 1:
			return new SinglePlaneInfoEntity();
		case 2:
			return new DoublePlaneInfoEntity();
		case 3:
			return new ReturnDoublePlaneInfoEntity();
		default:
			return null;
		}
	}

	private static String getRegex3() {
		String regex = "<tbody>(.+?)</tbody>";
		return regex;
	}

	private static String getRegex4() {
		String regex = "<tr>\\s*?<td.*?>(.*?)</td>\\s*?<td.*?>(.*?)</td>\\s*?<td.*?>\\s*?<strong>(.+?)<.+?<br/>(.+?)\\s*?</td>(.+)";
		return regex;
	}

	private static String getRegex5() {
		String regex = "<td.+?>.+?Class'\\s*?,\\s*?'(.+?)'\\s*?,this\\s*?,\\s*?'(.+?)'.*?/>\\s*?<strong>(.*?)</strong></td>";
		return regex;
	}

	@Override
	public List<Object> paraseToVo(Object fetchObject) throws Exception {
		return (List<Object>) fetchObject;
	}

	@Override
	public String getUrl() throws Exception {
		return null;
	}

	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {
		return true;
	}
}
